package service.impl;

import handler.MessageHandler;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Date;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import pojo.User;
import protocal.DataPackage;
import protocal.DataPackage.MessageType;
import protocal.DataPackageFilter;
import protocal.Filter;
import service.Service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import dao.UserDao;
import dao.impl.UserDaoImpl;
import data.UserTable;

public class ChatServiceImpl extends Thread implements Service{
	
	private final static Logger logger = LogManager.getLogger(ChatServiceImpl.class);
	
	private Socket socket;
	private BufferedReader reader;
	private BufferedWriter writer;
	private String serviceName;
	private boolean active;

	public ChatServiceImpl(Socket socket) {
		super();
		this.socket = socket;
		try {
			reader = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
			writer = new BufferedWriter(new OutputStreamWriter(this.socket.getOutputStream()));
		} catch (IOException e) {
			logger.error(e);
		}
		active = true;
	}
	
	public boolean isActive() {
		return active;
	}

	public void setActive(boolean active) {
		this.active = active;
	}

	public String getServiceName() {
		return serviceName;
	}

	public BufferedReader getReader() {
		return reader;
	}

	public BufferedWriter getWriter() {
		return writer;
	}

	public void run() {
		service();
	}
	
	public void close(){
		try {
			writer.close();
			reader.close();
			socket.close();
		} catch (IOException e) {
			logger.error(e);
		}
	}
	
	private boolean login(DataPackage dataPackage) throws JsonProcessingException, IOException{
		String username = dataPackage.getFromeName();
		UserTable userTable = UserTable.getInstance(); 
		ObjectMapper mapper = new ObjectMapper();
		UserDao userDao = new UserDaoImpl();
		DataPackage dataPackage2 = new DataPackage("\\",serviceName,MessageType.LOGIN,null,System.currentTimeMillis());
		User user = userDao.findByName(username);
		if (user==null) {
			dataPackage2.setMessageData("fail:user not regsiter");
			writer.write(mapper.writeValueAsString(dataPackage2)+"\n");
			writer.flush();
			return false;
		}
		if (!user.getPassword().equals(dataPackage.getMessageData())) {
			dataPackage2.setMessageData("fail:wrong password");
			writer.write(mapper.writeValueAsString(dataPackage2)+"\n");
			writer.flush();
			return false;
		}
		if (userTable.getUers().containsKey(username)) {
			dataPackage2.setMessageData("fail:user alady login");
			writer.write(mapper.writeValueAsString(dataPackage2)+"\n");
			writer.flush();
			return false;
		}
		serviceName = username;
		userTable.add(this);
		dataPackage2.setMessageData("success");
		System.out.println(userTable.getUers().toString());
		writer.write(mapper.writeValueAsString(dataPackage2)+"\n");
		writer.flush();
		return true;
	}

	@Override
	public void service() {
		Filter filter = new DataPackageFilter();
		ObjectMapper mapper = new ObjectMapper();
		MessageHandler handler = new MessageHandler();
		while (active) {
			try {
				String data = reader.readLine();
				DataPackage dataPackage = mapper.readValue(data, DataPackage.class);
				logger.info(dataPackage.toString());
				if (!filter.filter(dataPackage)) {
					continue;
				}
				if (dataPackage.getMessageType()==MessageType.LOGIN) {
					if (!login(dataPackage)) {
						continue;
					}
				}
				if (dataPackage.getMessageType()==MessageType.LOGOUT) {
					UserTable userTable = UserTable.getInstance();
					userTable.remove(dataPackage.getFromeName());
					active = false;
				}
				logger.info(dataPackage.toString());
				handler.handle(dataPackage);
			} catch (IOException e) {
				logger.error(e);
				UserTable userTable = UserTable.getInstance();
				Map<String, ChatServiceImpl> users = userTable.getUers();
				boolean userLogin = serviceName!=null&&users!=null&&!users.isEmpty()&&users.containsKey(serviceName);
				if (userLogin) {
					userTable.remove(serviceName);
					DataPackage dataPackage = new DataPackage();
					dataPackage.setFromeName(serviceName);
					dataPackage.setMessageType(MessageType.LOGOUT);
					dataPackage.setToName("\\");
					dataPackage.setTime(new Date().getTime());
					handler.handle(dataPackage);
				}
				active = false;
			}
		}
		close();
		
	}

}
